/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#include "Keyboard.h"
#include <win32/win32.h>
#include <Converter.h>
#include <sstream>

namespace liba
{
namespace input
{
namespace hard
{
namespace windows
{

Keyboard::Keyboard()
:	symbol_symap( 0, "KeyNone" )
{

	symbol_symap.add( VK_ESCAPE, "Esc" );
	symbol_symap.add( VK_RETURN, "Enter" );
	symbol_symap.add( VK_LEFT, "Left" );
	symbol_symap.add( VK_UP, "Up" );
	symbol_symap.add( VK_RIGHT, "Right" );
	symbol_symap.add( VK_DOWN, "Down" );
	symbol_symap.add( VK_SPACE, "Space" );
	symbol_symap.add( VK_DELETE, "Delete" );
	symbol_symap.add( VK_BACK, "BackSpace" );
	symbol_symap.add( VK_SHIFT, "Shift" );
	symbol_symap.add( VK_CONTROL, "Ctrl" );
	symbol_symap.add( VK_ADD, "Plus" );
	symbol_symap.add( VK_SUBTRACT, "Minus" );
	symbol_symap.add( VK_TAB, "Tab" );
	symbol_symap.add( VK_F1, "F1" );
	symbol_symap.add( VK_F2, "F2" );
	symbol_symap.add( VK_F3, "F3" );
	symbol_symap.add( VK_F4, "F4" );
	symbol_symap.add( VK_F5, "F5" );
	symbol_symap.add( VK_F6, "F6" );
	symbol_symap.add( VK_F7, "F7" );
	symbol_symap.add( VK_F8, "F8" );
	symbol_symap.add( VK_F9, "F9" );
	symbol_symap.add( VK_F10, "F10" );
	symbol_symap.add( VK_F11, "F11" );
	symbol_symap.add( VK_F12, "F12" );

	symbol_symap.add( 0x30, "0" );
	symbol_symap.add( 0x31, "1" );
	symbol_symap.add( 0x32, "2" );
	symbol_symap.add( 0x33, "3" );
	symbol_symap.add( 0x34, "4" );
	symbol_symap.add( 0x35, "5" );
	symbol_symap.add( 0x36, "6" );
	symbol_symap.add( 0x37, "7" );
	symbol_symap.add( 0x38, "8" );
	symbol_symap.add( 0x39, "9" );

	symbol_symap.add( 0x41, "A" );
	symbol_symap.add( 0x42, "B" );
	symbol_symap.add( 0x43, "C" );
	symbol_symap.add( 0x44, "D" );
	symbol_symap.add( 0x45, "E" );
	symbol_symap.add( 0x46, "F" );
	symbol_symap.add( 0x47, "G" );
	symbol_symap.add( 0x48, "H" );
	symbol_symap.add( 0x49, "I" );
	symbol_symap.add( 0x4A, "J" );
	symbol_symap.add( 0x4B, "K" );
	symbol_symap.add( 0x4C, "L" );
	symbol_symap.add( 0x4D, "M" );
	symbol_symap.add( 0x4E, "N" );
	symbol_symap.add( 0x4F, "O" );
	symbol_symap.add( 0x50, "P" );
	symbol_symap.add( 0x51, "Q" );
	symbol_symap.add( 0x52, "R" );
	symbol_symap.add( 0x53, "S" );
	symbol_symap.add( 0x54, "T" );
	symbol_symap.add( 0x55, "U" );
	symbol_symap.add( 0x56, "V" );
	symbol_symap.add( 0x57, "W" );
	symbol_symap.add( 0x58, "X" );
	symbol_symap.add( 0x59, "Y" );
	symbol_symap.add( 0x5A, "Z" );

	for( int i = 0; i < 256; ++i )
	{
		if( !symbol_symap.is_exists_first( i ) )
		{
			std::stringstream ss;
			ss << "Key#" << i;
			symbol_symap.add( i, ss.str() );
		}
	}

// VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39)
// VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A)

/*
#define VK_CANCEL         0x03

#define VK_TAB            0x09

#define VK_CLEAR          0x0C

#define VK_MENU           0x12
#define VK_PAUSE          0x13
#define VK_CAPITAL        0x14

#define VK_KANA           0x15
#define VK_HANGEUL        0x15
#define VK_HANGUL         0x15
#define VK_JUNJA          0x17
#define VK_FINAL          0x18
#define VK_HANJA          0x19
#define VK_KANJI          0x19


#define VK_CONVERT        0x1C
#define VK_NONCONVERT     0x1D
#define VK_ACCEPT         0x1E
#define VK_MODECHANGE     0x1F

#define VK_PRIOR          0x21
#define VK_NEXT           0x22
#define VK_END            0x23
#define VK_HOME           0x24
#define VK_SELECT         0x29
#define VK_PRINT          0x2A
#define VK_EXECUTE        0x2B
#define VK_SNAPSHOT       0x2C
#define VK_INSERT         0x2D
#define VK_HELP           0x2F

// VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39)
// VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A)

#define VK_LWIN           0x5B
#define VK_RWIN           0x5C
#define VK_APPS           0x5D

#define VK_NUMPAD0        0x60
#define VK_NUMPAD1        0x61
#define VK_NUMPAD2        0x62
#define VK_NUMPAD3        0x63
#define VK_NUMPAD4        0x64
#define VK_NUMPAD5        0x65
#define VK_NUMPAD6        0x66
#define VK_NUMPAD7        0x67
#define VK_NUMPAD8        0x68
#define VK_NUMPAD9        0x69
#define VK_MULTIPLY       0x6A
#define VK_ADD            0x6B
#define VK_SEPARATOR      0x6C
#define VK_SUBTRACT       0x6D
#define VK_DECIMAL        0x6E
#define VK_DIVIDE         0x6F
#define VK_F13            0x7C
#define VK_F14            0x7D
#define VK_F15            0x7E
#define VK_F16            0x7F
#define VK_F17            0x80
#define VK_F18            0x81
#define VK_F19            0x82
#define VK_F20            0x83
#define VK_F21            0x84
#define VK_F22            0x85
#define VK_F23            0x86
#define VK_F24            0x87

#define VK_NUMLOCK        0x90
#define VK_SCROLL         0x91

//
// VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys.
// Used only as parameters to GetAsyncKeyState() and GetKeyState().
// No other API or message will distinguish left and right keys in this way.
//
#define VK_LSHIFT         0xA0
#define VK_RSHIFT         0xA1
#define VK_LCONTROL       0xA2
#define VK_RCONTROL       0xA3
#define VK_LMENU          0xA4
#define VK_RMENU          0xA5
*/
}

Keyboard::~Keyboard()
{}

void Keyboard::key_up( int scan_code )
{
	Manager::add_event( Event( get_name(), get_name_by_code( scan_code ), false ) );
}

void Keyboard::key_down( int scan_code )
{
	Manager::add_event( Event( get_name(), get_name_by_code( scan_code ), true ) );
}

void Keyboard::key_char( wchar_t letter )
{
	Manager::add_event( Event( get_name(), std::wstring( 1, letter ) ) );
}

std::string Keyboard::get_name()const
{
	return "Keyboard";
}

double Keyboard::get_axis_position( const std::string & axis_name )const
{
	int scan_code = get_code_by_name( axis_name );
	SHORT state = GetAsyncKeyState( scan_code );

	bool pressed = state & 0x8000;
	return pressed;
}

Manager::AxisType Keyboard::get_axis_type( const std::string & axis_name )const
{
	if( symbol_symap.is_exists_second( axis_name ) )
		return Manager::BUTTON;

	return Manager::NONE;
}

std::string Keyboard::get_name_by_code( int scan_code )const
{
	return symbol_symap.get_second_by_first( scan_code );
}

int Keyboard::get_code_by_name( const std::string & name )const
{
	return symbol_symap.get_first_by_second( name );
}

} // namespace windows
} // namespace hard
} // namespace input
} // namespace liba


